package org.budo.mybatis.dao.base;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.budo.mybatis.dao.MybatisDao;
import org.budo.support.dao.page.Page;
import org.budo.support.spring.context.aware.AbstractApplicationContextAware;

/**
 * @author limingwei2
 * @param <T>
 * @param <ID>
 */
public class MybatisBaseDao<Entity, Id> extends AbstractApplicationContextAware {
    private Class<Entity> entityType;

    private Class<Id> idType;

    private MybatisDao mybatisDao;

    public MybatisDao getMybatisDao() {
        if (null == mybatisDao) {
            mybatisDao = this.getApplicationContext().getBean(MybatisDao.class);
        }
        return mybatisDao;
    }

    @SuppressWarnings("unchecked")
    protected Class<Entity> getEntityType() {
        if (null == entityType) {
            entityType = (Class<Entity>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return entityType;
    }

    @SuppressWarnings("unchecked")
    protected Class<Id> getIdType() {
        if (null == idType) {
            idType = (Class<Id>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        }
        return idType;
    }

    @SuppressWarnings("unchecked")
    public Id insert(Entity entity) {
        return (Id) this.getMybatisDao().insert(this.getEntityType(), entity);
    }

    public Boolean save(Entity entity) {
        return this.getMybatisDao().save(this.getEntityType(), entity);
    }

    public Boolean saveIgnoreNull(Entity entity) {
        return this.getMybatisDao().saveIgnoreNull(this.getEntityType(), entity);
    }

    @SuppressWarnings("unchecked")
    public Id insertIgnoreNull(Entity entity) {
        return (Id) this.getMybatisDao().insertIgnoreNull(this.getEntityType(), entity);
    }

    public Boolean saveBatch(List<Entity> list) {
        return this.getMybatisDao().saveBatch(this.getEntityType(), list);
    }

    @SuppressWarnings("unchecked")
    public Id[] insertBatch(List<Entity> list) {
        return (Id[]) this.getMybatisDao().insertBatch(this.getEntityType(), list);
    }

    public Entity findById(Id id) {
        return this.getMybatisDao().findById(this.getEntityType(), (Serializable) id);
    }

    public Boolean update(Entity entity) {
        return this.getMybatisDao().update(this.getEntityType(), entity);
    }

    public Boolean deleteById(Id id) {
        return this.getMybatisDao().deleteById(this.getEntityType(), (Serializable) id);
    }

    public Integer deleteByIds(Id[] ids) {
        return this.getMybatisDao().deleteByIds(this.getEntityType(), (Serializable[]) ids);
    }

    public Boolean updateIgnoreNull(Entity entity) {
        return this.getMybatisDao().updateIgnoreNull(this.getEntityType(), entity);
    }

    public Entity findByExample(Entity example) {
        return this.getMybatisDao().findByExample(this.getEntityType(), example);
    }

    public List<Entity> list(Page page) {
        return this.getMybatisDao().list(this.getEntityType(), page);
    }

    public List<Entity> listByIds(Id[] ids) {
        return this.getMybatisDao().listByIds(this.getEntityType(), (Serializable[]) ids);
    }
}